package server.multiServlet;

import lombok.Data;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.InputStream;
import java.util.List;

@Data
public class Catalina implements LifeCycle {

    private final String SERVER_XML = "server.xml";
    private Server server = new Server();

    public void load() {
        InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(SERVER_XML);
        SAXReader saxReader = new SAXReader();

        try {
            Document document = saxReader.read(resourceAsStream);
            Element rootElement = document.getRootElement();

            List<Element> serviceElements = rootElement.selectNodes("//Service");
            composeServer(serviceElements);
        } catch (Exception e) {
            System.err.println("compose server error");
        }
    }


    @Override
    public void init() {
        server.getServices().forEach(Service::init);
    }

    private void composeServer(List<Element> serviceElements) {
        serviceElements.forEach(element -> {
            Service service = new Service();
            server.getServices().add(service);
            List<Element> connectorElements = element.selectNodes("//Connector");
            Element engineElement = (Element) element.selectSingleNode("//Engine");
            composeService(service, connectorElements, engineElement);
        });

    }

    private void composeService(Service service, List<Element> connectorElements, Element engineElement) {
        connectorElements.forEach(connectorElement -> {
            String portStr = connectorElement.attributeValue("port");

            Integer port = Integer.parseInt(portStr);
            Connector connector = new Connector(port);
            service.getConnector().add(connector);
        });

        List<Element> hostElements = engineElement.selectNodes("//Host");

        composeEngine(service.getContainer().getEngine(), hostElements);
    }

    private void composeEngine(Engine engine, List<Element> hostElements) {
        hostElements.forEach(hostElement -> {

            String name = hostElement.attributeValue("name");
            String appBase = hostElement.attributeValue("appBase");

            Host host = Host.of(name, appBase);

            engine.getMapperHosts().add(host);

            List<Element> contextElements = hostElement.selectNodes("//Context");
            composeHost(host, contextElements);
        });

    }

    private void composeHost(Host mapperHost, List<Element> contextElements) {
        contextElements.forEach(contextElement->{
            String path = contextElement.attributeValue("path");
            String docBase = contextElement.attributeValue("docBase");
            Context context = new Context(path, docBase);
            mapperHost.getContexts().add(context);
        });
    }
}
